/**
 * @Author: ls-mac
 * @Date:   2018-09-15T13:56:08+08:00
 * @Last modified by:   ls-mac
 * @Last modified time: 2018-11-11T19:47:26+08:00
 */

import React, { PureComponent } from 'react';
import { Table, Input, InputNumber, Select, Form } from 'antd';
import styles from './index.less';

const FormItem = Form.Item;
const EditableContext = React.createContext();

const EditableRow = ({ form, index, ...props }) => (
  <EditableContext.Provider value={form}>
    <tr {...props} />
  </EditableContext.Provider>
);

const EditableFormRow = Form.create()(EditableRow);

class EditableCell extends React.Component {
  constructor(props) {
    super(props);
  }

  changeSelect = (value, dataIndex) => {
    const { record } = this.props;

    if (dataIndex === 'brand' && record.warehouse && record.shopSign && record.spec) {
      for (const productDict of record.brand.brandList) {
        if (productDict.productId === value) {
          record.shopSign.signList = productDict.bmShopSignList;
          record.spec.specList = productDict.bmSpecInfoList;
          record.warehouse.deptList = productDict.bmDepotInfoList;
          record.form.setFieldsValue({ brand: '' });
          record.form.setFieldsValue({ shopSign: '' });
          record.form.setFieldsValue({ warehouse: '' });
          record.form.setFieldsValue({ spec: '' });
          break;
        }
      }
    }
  };

  onInputChange = (dataIndex, value) => {
    if (dataIndex === 'weight') {
      const { computetransprice, record, handleChangeTableField } = this.props;
      record[this.props.dataIndex] = value;
      handleChangeTableField(dataIndex, record[dataIndex]);

      if (computetransprice) {
        const formValues = record.form.getFieldsValue(['warehouse', 'brand']);
        if (formValues.warehouse && formValues.brand) {
          const payload = {};
          payload.weight = value;
          for (const dept of record.warehouse.deptList) {
            if (dept.depotId === formValues.warehouse) {
              payload.deliveryProvince = dept.depotProvince;
              payload.deliveryCity = dept.depotCity;
              payload.deliveryCountry = dept.depotCounty;
              break;
            }
          }

          for (const productDict of record.brand.brandList) {
            if (productDict.productId === formValues.brand) {
              payload.productType = productDict.productType;
              payload.productCode = productDict.productCode;
              break;
            }
          }

          if (payload.productType && payload.deliveryCountry) computetransprice(payload, record);
        }
      }
    }
  };

  getInputNumer = (dataIndex, record) => {
    return (
      <InputNumber
        disabled={record[dataIndex] ? record[dataIndex].disabled : false}
        min={0}
        max={999999999}
        onChange={val => this.onInputChange(dataIndex, val)}
        precision={3}
      />
    );
  };

  getInput = (dataIndex, record) => {
    if (this.props.inputType === 'select') {
      const Option = Select.Option;
      const optionsItems = [];
      let width = 160;
      let showSearch = false;
      switch (dataIndex) {
        case 'warehouse':
          width = 140;
          showSearch = true;
          const deptList = record[dataIndex].deptList;
          for (const option of deptList) {
            optionsItems.push(
              <Option value={option.depotId} key={option.depotId}>
                {option.depotName}
              </Option>
            );
          }
          break;
        case 'brand':
          width = 100;
          const brandList = record[dataIndex].brandList;
          for (const option of brandList) {
            optionsItems.push(
              <Option value={option.productId} key={option.productId}>
                {option.productName}
              </Option>
            );
          }
          break;
        case 'spec':
          width = 120;
          const specList = record[dataIndex].specList;
          for (const option of specList) {
            optionsItems.push(
              <Option value={option.specValue} key={option.specValue}>
                {option.specValue}
              </Option>
            );
          }
          break;
        case 'shopSign':
          width = 200;
          showSearch = true;
          const signList = record[dataIndex].signList;
          for (const option of signList) {
            optionsItems.push(
              <Option value={option.shopsignId} key={option.shopsignId}>
                {option.shopsignName}
              </Option>
            );
          }
          break;
        default:
          for (const option of options) {
            optionsItems.push(
              <Option value={option.key} key={option.key}>
                {option.name}
              </Option>
            );
          }
      }

      return (
        <Select
          style={{ width }}
          showSearch={showSearch}
          filterOption={(input, option) => option.props.children.indexOf(input.toLowerCase()) >= 0}
          onChange={value => this.changeSelect(value, dataIndex)}
        >
          {optionsItems}
        </Select>
      );
    }
    return <Input disabled={record[dataIndex] ? record[dataIndex].disabled : false} />;
  };

  render() {
    const {
      editing,
      dataIndex,
      title,
      inputType,
      record,
      index,
      handleChangeTableField,
      computetransprice,
      ...restProps
    } = this.props;
    return (
      <EditableContext.Consumer>
        {form => {
          const { getFieldDecorator } = form;
          if (record && !record.form) {
            record.form = form;
          }
          return (
            <td {...restProps}>
              {editing ? (
                this.props.inputType === 'inputNumber' ? (
                  <FormItem style={{ margin: 0 }}>
                    {getFieldDecorator(dataIndex, {
                      initialValue: record[dataIndex] ? record[dataIndex].value : '',
                    })(this.getInputNumer(dataIndex, record))}
                  </FormItem>
                ) : (
                  <FormItem style={{ margin: 0 }}>
                    {getFieldDecorator(dataIndex, {
                      initialValue: record[dataIndex] ? record[dataIndex].value : '',
                    })(this.getInput(dataIndex, record))}
                  </FormItem>
                )
              ) : (
                restProps.children
              )}
            </td>
          );
        }}
      </EditableContext.Consumer>
    );
  }
}

function initTotalList(columns) {
  const totalList = [];
  columns.forEach(column => {
    if (column.needTotal) {
      totalList.push({ ...column, total: 0 });
    }
  });
  return totalList;
}

class StandardTable extends PureComponent {
  constructor(props) {
    super(props);
    const { columns } = props;
    const needTotalList = initTotalList(columns);

    this.state = {
      selectedRowKeys: [],
      needTotalList,
    };
  }

  componentWillReceiveProps(nextProps) {
    // clean state
    if (nextProps.selectedRows == undefined) {
      return;
    }
    if (!nextProps.selectedRows) {
      const needTotalList = initTotalList(nextProps.columns);
      this.state = {
        selectedRowKeys: '',
        needTotalList,
      };
    }

    if (nextProps.selectedRows && nextProps.selectedRows.length === 0) {
      const needTotalList = initTotalList(nextProps.columns);
      this.setState({
        selectedRowKeys: [],
        needTotalList,
      });
    }
  }

  handleRowSelectChange = (selectedRowKeys, selectedRows) => {
    const { needTotalList: list } = this.state;
    const { onSelectRow } = this.props;
    let needTotalList = [...list];
    needTotalList = needTotalList.map(item => {
      return {
        ...item,
        total: selectedRows.reduce((sum, val) => {
          return sum + parseFloat(val[item.dataIndex], 10);
        }, 0),
      };
    });

    if (onSelectRow) {
      onSelectRow(selectedRows);
    }

    this.setState({ selectedRowKeys, needTotalList });
  };

  cleanSelectedKeys = () => {
    this.handleRowSelectChange([], []);
  };

  render() {
    const { selectedRowKeys } = this.state;
    const {
      data: { list },
      loading,
      rowKey,
      handleChangeTableField,
      computetransprice,
    } = this.props;

    const components = {
      body: {
        row: EditableFormRow,
        cell: EditableCell,
      },
    };

    const columns = this.props.columns.map(col => {
      if (!col.editable) {
        return col;
      }
      return {
        ...col,
        onCell: record => ({
          record,
          inputType: col.inputType,
          dataIndex: col.dataIndex,
          title: col.title,
          editing: record.editable,
          handleChangeTableField,
          computetransprice,
        }),
      };
    });

    const rowSelection =
      selectedRowKeys == undefined
        ? undefined
        : {
            selectedRowKeys,
            onChange: this.handleRowSelectChange,
            getCheckboxProps: record => ({
              disabled: record.disabled,
            }),
          };
    return (
      <div className={styles.editableTable}>
        <Table
          loading={loading}
          components={components}
          rowKey={rowKey || 'key'}
          rowSelection={rowSelection}
          dataSource={list}
          columns={columns}
          onChange={this.handleTableChange}
          pagination={false}
        />
      </div>
    );
  }
}

export default StandardTable;
